package com.shanghaionstar.discover.charge;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.onstar.cn.api.VehicleService;
import com.onstar.cn.common.exception.HttpException;
import com.onstar.cn.common.log.LogManager;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.framework.annotation.http.HeadsValue;
import com.onstar.cn.framework.annotation.http.Request;
import com.onstar.cn.framework.network.entity.RequestEntity;
import com.onstar.cn.framework.network.enumtype.HttpAccept;
import com.onstar.cn.framework.network.enumtype.HttpMethod;
import com.onstar.cn.framework.network.enumtype.Language;
import com.onstar.cn.framework.network.http.ResponseHandler;
import com.onstar.cn.framework.network.http.Sender;
import com.onstar.cn.framework.utils.GsonHelper;
import com.onstar.cn.mag.enumtype.RemoteCommandsType;
import com.onstar.cn.sqlite.entities.PollingEntity;
import com.onstar.cn.vehicle.entity.ErrorInfo;
import com.onstar.cn.vehicle.entity.VehicleAlert;
import com.onstar.cn.vehicle.entity.VehicleCommand;
import com.onstar.cn.vehicle.entity.VehicleLockDoor;
import com.onstar.cn.vehicle.entity.VehicleUnLockDoor;
import com.shanghaionstar.R;
import com.shanghaionstar.service.VehicleManager;
import com.shanghaionstar.utils.ApplicationUtil;
import com.shanghaionstar.utils.BusinessUtil;
import com.shanghaionstar.utils.NetConnectUtil;
import com.shanghaionstar.utils.PlaySoundUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RemoteCommandUtil {

	private LogManager log = LogManager.getInstance();
	private Context context;
	private VehicleManager manager;
	private Handler handler;

	private Map<String, Boolean> alertParam;
	
	
	public RemoteCommandUtil(Context context, Handler handler) {
		this.context = context;
		manager = new VehicleManager(context, Constants.CURRENT_SERVER_URL);
		this.handler = handler;
	}

	public void setAlertParam(Map<String, Boolean> alertParam) {
		this.alertParam = alertParam;
	}

	public void command(final RemoteCommandsType commandType) {
		command(commandType, null);
	}

	@Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.POST)
	public void command(final RemoteCommandsType commandType, String sBody) {
		VehicleService service = new VehicleService(Constants.CURRENT_SERVER_URL);
		RequestEntity requestEntity = NetConnectUtil.getAuthRequestEntity(context);
		String body = "";
		if (sBody != null) {
			body = sBody;
		} else {
			switch (commandType) {
				case COMMANDS_LOCK_DOOR:
					body = lock();
					break;
				case COMMANDS_UNLOCK_DOOR:
					body = unlock();
					break;
				case COMMANDS_START:
					// no body
					break;
				case COMMANDS_CANCEL_START:
					// no body
					break;
				case COMMANDS_ALERT:
					body = alert();
					break;
				default:
					break;
			}
		}
		service.commands(requestEntity, commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),body);
		Sender sender = new Sender();
		BusinessUtil.initPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
		sender.send(requestEntity, new ResponseHandler() {
			@Override
			public void onSuccess(String tag, String json) {
				Message msg = handler.obtainMessage();
				log.d(json);
				JSONObject error = GsonHelper.getJsonObject(json, "error");
				JSONObject commandResponse = GsonHelper.getJsonObject(json, "commandResponse");
				if (error != null) {
					try {
						String code = error.getString("code");
				    		String description = error.getString("description");
						ErrorInfo errorInfo = new ErrorInfo();
						errorInfo.setCode(code);
						errorInfo.setMsg(description);
						msg.getData().putSerializable("errorInfo", errorInfo);
						msg.getData().putSerializable("commandType", commandType);
						handler.sendMessage(msg);
					} catch (JSONException e) {
						log.e(e.getMessage());
						processError(commandType, msg, e);
					}
				} else if (commandResponse != null) {
					String url;
					try {
						url = commandResponse.getString("url");
						String requestId = url.substring(url.lastIndexOf("s") + 2, url.length());
						msg.what = Constants.SERVICE_RESPONSE_INPROGRESS;
						msg.getData().putSerializable("commandType", commandType);
						handler.sendMessage(msg);
						startPollVehicleStatus(commandType, requestId);
					} catch (JSONException e) {
						e.printStackTrace();
						processError(commandType, msg, e);
					}
				}
			}

			@Override
			public void onError(String tag, HttpException e) {
				BusinessUtil.updateToFailPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
				log.d(e.getMessage());
				Message msg = handler.obtainMessage();
				msg.what = Constants.SERVICE_HTTP_ERROR;
				msg.getData().putSerializable("HttpException", e);
				msg.getData().putSerializable("commandType", commandType);
				handler.sendMessage(msg);
//				processError(commandType, msg, e);
//				AlertDialogUtil.showDialogByExceptionCode(context,e);
			}

//			@Override
//			public void onExpired() {
//				AuthTokenRequestEntity entity = BusinessUtil.createAuthTokenRequestEntity();
//				AuthorizeUtil authorizeUtil = new AuthorizeUtil(context);
//				authorizeUtil.setResultListener(new AuthorResultListener() {
//					@Override
//					public void onSuccess(AuthorizeType type) {
//						
//					}
//
//					@Override
//					public void onFail(AuthorizeType type, HttpException e) {
//						
//					}
//					
//				});
//				authorizeUtil.pinReauthenticationForNoPin(entity);
//			}
		}, getClass(), "command", RemoteCommandsType.class, String.class);
	}

	public void startPollVehicleStatus(RemoteCommandsType commandsType, String requestId) {
		PollingEntity entity = new PollingEntity();
		entity.setVin(ApplicationUtil.getInstance().getVin());
		entity.setToken(ApplicationUtil.getInstance().getToken());
		entity.setRequestType(commandsType.value());
		entity.setRequestId(requestId);
		manager.startPoll(entity);
	}

	private void processError(final RemoteCommandsType commandType, Message msg, Exception e) {
		BusinessUtil.updateToFailPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
		ErrorInfo errorInfo = BusinessUtil.getErrorInfoByException(context, e);
		msg.what = Constants.SERVICE_RESPONSE_FAILURE;
		msg.getData().putSerializable("errorInfo", errorInfo);
		msg.getData().putSerializable("commandType", commandType);
		handler.sendMessage(msg);
	}

	private String lock() {
		VehicleCommand vecicleCommand = new VehicleCommand();
		VehicleLockDoor lockDoor = new VehicleLockDoor();
		lockDoor.setDelay("0");
		vecicleCommand.setLockDoorRequest(lockDoor);
		return GsonHelper.toJson(vecicleCommand);
	}

	private String unlock() {
		VehicleCommand vecicleCommand = new VehicleCommand();
		VehicleUnLockDoor unlockDoor = new VehicleUnLockDoor();
		unlockDoor.setDelay("0");
		vecicleCommand.setUnlockDoorRequest(unlockDoor);
		return GsonHelper.toJson(vecicleCommand);
	}

	private String alert() {
		String[] array = new String[]{};
		List<String> list = new ArrayList<String>();
		if(alertParam.get("Flash")) {
			list.add("Flash");
		}
		if(alertParam.get("Honk")) {
			list.add("Honk");
		}
		VehicleCommand vecicleCommand = new VehicleCommand();
		VehicleAlert alert = new VehicleAlert();
		alert.setDelay("0");
		//		alert.setDuration("60");
		//IDT1 个例只能为30
		alert.setDuration((ApplicationUtil.getInstance().getAlertDuration()!=-1?ApplicationUtil.getInstance().getAlertDuration():ApplicationUtil.ALERT_DURATION_DEF)+"");
		alert.setAction(list.toArray(array));
		alert.setOverride(new String[]{"DoorOpen", "IgnitionOn"});
		vecicleCommand.setAlertRequest(alert);
		return GsonHelper.toJson(vecicleCommand);
	}

	public static String getRequestStringByType(Context context, RemoteCommandsType requestType) {
		String str = "";
		switch (requestType) {
			case COMMANDS_LOCK_DOOR:
				str = context.getResources().getString(R.string.lock_hint);
				break;
			case COMMANDS_UNLOCK_DOOR:
				str = context.getResources().getString(R.string.unlock_hint);
				break;
			case COMMANDS_START:
				str = context.getResources().getString(R.string.start_hint);
				break;
			case COMMANDS_CANCEL_START:
				str = context.getResources().getString(R.string.stop_hint);
				break;
			case COMMANDS_ALERT:
				str = context.getResources().getString(R.string.alert_hint);
				break;
			default:
				break;
		}
		return str;
	}

    public static void playSound(Context context, RemoteCommandsType commandsType) {
        switch (commandsType) {
            case COMMANDS_LOCK_DOOR:
            case COMMANDS_UNLOCK_DOOR:
                PlaySoundUtil.playCustomSound(context, true, R.raw.open_car);
                break;
            case COMMANDS_START:
                PlaySoundUtil.playCustomSound(context, true, R.raw.start_car);
                break;
            case COMMANDS_CANCEL_START:
                PlaySoundUtil.playCustomSound(context, true, R.raw.cancel_start);
                break;
            case COMMANDS_ALERT:
                PlaySoundUtil.playCustomSound(context, true, R.raw.whistle);
                break;
            default:
                break;
        }
    }
    
}
